import { Theme } from "@/hooks/theme";
import classnames from "classnames";
import { DragEventHandler, useRef } from "react";
import { get_ele_left } from "../../utils/dom/get_ele_left";
import { get_ele_top } from "../../utils/dom/get_ele_top";
import { Slot } from "../WorkspacesView";
import { DockType } from "./DockType";
import { IEditorInfo } from "./IEditorInfo";
import styles from "./style.module.scss";

export interface IContentViewProps extends React.HTMLAttributes<HTMLDivElement> {
  actived_tab?: IEditorInfo;
  tabs?: IEditorInfo[];
  ws_slot?: Slot;
  ref_dragging?: React.RefObject<[Slot, IEditorInfo] | undefined>;
  on_somethings_drop?(dock_type: DockType): void;
}
export function ContentView(props: IContentViewProps) {
  const ref_drag_count = useRef(0)
  const ref_ele_root = useRef<HTMLDivElement | null>(null)
  const ref_ele_indicator = useRef<HTMLDivElement | null>(null)
  const {
    children, className, ws_slot, on_somethings_drop, ref_dragging,
    onDragEnter, onDragLeave, onDragOver, onDrop, tabs, actived_tab,
    ..._p
  } = props;

  const root_classname = classnames(styles.editor_content, className)

  const set_ele_rect = (left: number, top: number, width: number, height: number) => {
    const ele = ref_ele_indicator.current;
    if (!ele) return;
    ele.style.left = '' + left + 'px';
    ele.style.top = '' + top + 'px';
    ele.style.width = '' + width + 'px';
    ele.style.height = '' + height + 'px';
  }
  const dockable = () => ref_dragging?.current && (tabs?.length !== 1 || tabs?.[0].uid !== ref_dragging.current?.[1].uid)

  const start_docking = () => {
    if (!dockable()) return;
    const ele = ref_ele_indicator.current;
    if (!ele) return;
    ele.classList.add(styles.docking_rect)
    ele.classList.add(styles.docking_rect_active)
  }

  const stop_docking = () => {
    console.log('')
    const ele = ref_ele_indicator.current;
    if (!ele) return;
    ele.classList.remove(styles.docking_rect_active)
  }

  const on_drag_enter: DragEventHandler<HTMLDivElement> = (e) => {
    ++ref_drag_count.current
    onDragEnter?.(e)
    if (ref_drag_count.current == 1) start_docking()
  }

  const on_drag_leave: DragEventHandler<HTMLDivElement> = (e) => {
    --ref_drag_count.current
    onDragLeave?.(e)
    if (ref_drag_count.current == 0) stop_docking()
  }

  const on_drag_over: DragEventHandler<HTMLDivElement> = (e) => {
    onDragOver?.(e)
    e.preventDefault();

    const ele = ref_ele_root.current
    if (!dockable()) return;
    if (!ele) return;
    const { width: w, height: h } = ele.getBoundingClientRect();
    switch (get_dock_type(e.nativeEvent, ele)) {
      case 'left': set_ele_rect(0, 0, w / 2, h); break;
      case 'right': set_ele_rect(w / 2, 0, w / 2, h); break;
      case 'up': set_ele_rect(0, 0, w, h / 2); break;
      case 'down': set_ele_rect(0, h / 2, w, h / 2); break;
      case 'full': set_ele_rect(0, 0, w, h); break;
    }
  }

  const on_drop: DragEventHandler<HTMLDivElement> = (e) => {
    onDrop?.(e)
    stop_docking()
    ref_drag_count.current = 0
    e.preventDefault();

    const ele = ref_ele_root.current
    if (!dockable()) return;
    if (!ele) return;

    const dock_type = get_dock_type(e.nativeEvent, ele)
    on_somethings_drop?.(dock_type)
  }
  const { theme } = Theme.use()
  return (
    <div {..._p}
      ref={ref_ele_root}
      className={root_classname}
      style={{ background: theme.token?.colorBgBase }}
      onDragEnter={on_drag_enter}
      onDragLeave={on_drag_leave}
      onDragOver={on_drag_over}
      onDrop={on_drop}>
      {children}
      <div ref={ref_ele_indicator} />
    </div>
  )
}
function get_dock_type(event: DragEvent, ele: HTMLElement): DockType {
  const { width: w, height: h } = ele.getBoundingClientRect();
  let { clientX: x, clientY: y } = event
  x -= get_ele_left(ele);
  y -= get_ele_top(ele);
  if (x < w * 0.3) return 'left';
  if (x >= w * 0.7) return 'right';
  if (y < h * 0.3) return 'up';
  if (y >= h * 0.7) return 'down';
  return 'full';
}